<template>
  <el-dialog
    v-model="dialogVisible"
    title="导入文件夹"
    width="600"
    align-center
  >
    <div class="upload-folder">
      <div class="tips">
        <p>1. 请点击特定区域进行文件夹导入；</p>
        <p>2. 或拖拽文件夹到特定区域以进行导入；</p>
      </div>

      <div
        class="upload-box"
        draggable="true"
        @click.stop="uploadFolderHandle"
        @drop="drop"
        @dragenter="(e) => e.preventDefault()"
        @dragover="(e) => e.preventDefault()"
      >
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
          <path
            fill="currentColor"
            d="M544 864V672h128L512 480 352 672h128v192H320v-1.6c-5.376.32-10.496 1.6-16 1.6A240 240 0 0 1 64 624c0-123.136 93.12-223.488 212.608-237.248A239.808 239.808 0 0 1 512 192a239.872 239.872 0 0 1 235.456 194.752c119.488 13.76 212.48 114.112 212.48 237.248a240 240 0 0 1-240 240c-5.376 0-10.56-1.28-16-1.6v1.6z"
          ></path>
        </svg>
        <div class="text">
          Drop file here or
          <em><el-link type="primary">click to upload</el-link> </em>
        </div>
      </div>
      <el-popover
        placement="top-start"
        title="上传结果"
        :width="200"
        trigger="hover"
      >
        <template #reference>
          <el-button text bg size="small">
            上传结果
            <el-icon style="margin-left: 10px"><InfoFilled /></el-icon>
          </el-button>
        </template>
        <!-- 上传结果 -->
        <el-scrollbar height="160px">
          <p
            v-for="item in uploadFileList"
            :key="item.id"
            class="upload-result-item"
          >
            {{ item.id }}
          </p>
        </el-scrollbar>
      </el-popover>
    </div>
    <template #footer>
      <el-button @click="dialogCancelHandle">取消</el-button>
      <el-button type="primary" @click="dialogConfirmHandle"> 导入 </el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { InfoFilled } from "@element-plus/icons-vue";
import { IFileTreeItem } from "../../../interface/FileTree";

const emit = defineEmits(["upload"]);

// 导入文件夹相关参数
const dialogVisible = ref(false);

// 记录需要创建的文件夹
const uploadFolderList = ref<string[]>([]);

const uploadFileList = ref<IFileTreeItem[]>([]);

/**
 * 打开弹窗
 */
function openDialog() {
  dialogVisible.value = true;
}
/**
 * 取消按钮
 */
function dialogCancelHandle() {
  dialogVisible.value = false;
}

/**
 * 确认按钮
 */
function dialogConfirmHandle() {
  dialogVisible.value = false;
  // emit 事件，在 FileTreeVue 中执行真正的创建操作
  emit("upload", {
    uploadFolderList: JSON.parse(JSON.stringify(uploadFolderList.value)),
    uploadFileList: JSON.parse(JSON.stringify(uploadFileList.value)),
  });
}

/**
 * 点击上传
 */

async function uploadFolderHandle() {
  // 每次选择，都会重置文件/文件夹列表
  uploadFolderList.value = [];
  uploadFileList.value = [];

  if (!Object.hasOwn(window, "showDirectoryPicker")) {
    ElMessage.warning("当前浏览器不支持点击导入，请拖拽文件至指定区域");
    return;
  }

  try {
    // FileSystemDirectoryHandle
    // https://developer.mozilla.org/zh-CN/docs/Web/API/FileSystemDirectoryHandle
    const dirHandle = await window.showDirectoryPicker();

    // 如果用户取消了选择或者打开文件夹失败
    if (!dirHandle) return;

    // 调用处理函数，递归进行文件/文件夹处理
    directoryPickerHandle(dirHandle);
  } catch (error) {
    console.error("==> ", error);
  }
}

/**
 * 点击上传
 * 文件系统目录选择器回调结果处理
 * @param { FileSystemDirectoryHandle } dirHandle
 */
function directoryPickerHandle(dirHandle: FileSystemDirectoryHandle) {
  // 1. 将该目录进行存储
  const rootpath = `/${dirHandle.name}`;
  uploadFolderList.value.push(rootpath);
  console.log("==> 根目录", rootpath);

  ElMessage.success("上传成功，请点击'上传结果'查看文件。");

  // 2. 递归解析文件夹内容
  async function entryFolder(handle: FileSystemDirectoryHandle) {
    for await (const item of handle.values()) {
      // 判断文件还是文件夹
      if (item.kind === "file") {
        // 创建文件读取器, 会返回 FileSystemFileHandle
        const fileHandle = await handle.getFileHandle(item.name);
        // 调用 getFile() 获取文件对象(File)
        const file = await fileHandle.getFile();
        const { parentName, name } = handle;
        const fullpath = `${parentName || ""}/${name}/${file.name}`;
        console.log("==> 文件完整路径：", fullpath);

        // 创建 Reader 读取器，读取文件内容
        const reader = new FileReader();
        reader.onload = () => {
          uploadFileList.value.push({
            id: fullpath,
            label: file.name,
            type: "File",
            content: reader.result as string,
          });
        };
        reader.readAsText(file, "UTF-8");
      } else if (item.kind === "directory") {
        // 创建文件夹读取器，返回 FolderSystemHandle
        const folderHandle = await handle.getDirectoryHandle(item.name);
        const fullpath = `/${handle.name}/${item.name}`;
        // 记录该路径
        uploadFolderList.value.push(fullpath);
        folderHandle.parentName = `/${handle.name}`;
        console.log("==> 文件夹完整路径：", fullpath);
        entryFolder(folderHandle);
      }
    }
  }

  // 3. 启动entry
  entryFolder(dirHandle);
}

/**
 * 拖拽上传
 * @param e
 */
function drop(e: DragEvent) {
  e.preventDefault();

  // 清空上传文件列表
  uploadFileList.value = [];
  uploadFolderList.value = [];

  const items = e.dataTransfer?.items;

  if (!items) return;

  ElMessage.success("上传成功，请点击'上传结果'查看文件。");

  for (const item of items) {
    // 获取文件系统句柄
    const entry = item.webkitGetAsEntry()!;
    dataTransferHandle(entry);
  }
}

/**
 * 拖拽上传
 * 递归解析拖拽的文件夹内容
 * @param entry
 */
async function dataTransferHandle(entry: FileSystemEntry) {
  if (!entry) return;

  // 通过判断 isFile isDirectory 来区分是文件还是文件夹
  if (entry.isFile) {
    const fileEntry = <FileSystemFileEntry>entry;

    fileEntry.file((file: File) => {
      console.log("==> 文件路径", entry.fullPath);
      // 创建 fileReader
      const reader = new FileReader();
      reader.readAsText(file, "UTF-8");
      reader.onload = async () => {
        uploadFileList.value.push({
          id: entry.fullPath,
          label: file.name,
          type: "File",
          content: reader.result as string,
        });
      };
    });
  }

  if (entry.isDirectory) {
    // 创建读取器
    const folderRntry = <FileSystemDirectoryEntry>entry;

    // 记录需要创建的文件夹路径
    console.log("==> 文件夹路径", folderRntry.fullPath);
    uploadFolderList.value.push(folderRntry.fullPath);

    const reader = folderRntry.createReader();
    reader.readEntries((files) => {
      files.forEach((file) => dataTransferHandle(file));
    });
  }
}

defineExpose({ openDialog });
</script>

<style lang="css" scoped>
.upload-folder .tips {
  color: #f56c6c;
}
.upload-folder .tips p {
  margin-bottom: 10px;
}
.upload-box {
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  border: dashed 1px #ccc;
  margin: 10px;
  padding: 10px;
}
.upload-box svg {
  height: 120px;
  opacity: 0.5;
}
.upload-box .text {
  margin-bottom: 10px;
}

.upload-result-item {
  margin: 4px 0;
}
</style>
